#include <arpa/inet.h>
#include <cJSON.h>
#include <errno.h>
#include <fcntl.h>
#include "list.h"
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <shmem.h>
#include <sys/socket.h>
#include <unistd.h>

struct modbus_node
{
	int key;		//唯一键值
	char name[128]; //数据点名称
	int type;		//数据点类型
	int addr;
};

struct msgbuf
{
	long mtype;		 //消息队列
	char mdata[256]; //上报传的json字符数据
};

struct modbus_node_list //定义内核链表结构体
{
	struct modbus_node node;
	struct list_head list;
};

union val_t {
	int b_val;	 //bool类型存储空间
	int i_val;	 //整形值存储空间
	float f_val; //浮点值存储空间
};

struct std_node
{
	int key;			 //唯一键值
	int type;			 //数据点类型
	int dev_type;		 //属于哪个设备
	union val_t old_val; //旧值
	union val_t new_val; //新值
	int ret;			 //采集成功0，采集失败-1,默认-1
};
#define N 64	 //
#define MODBUS 5 //最大设备数
char buf[1090];	 //定义读到数据的存放地址
int sockfd1;	 //用于读取数据的套接字
int sockfd2;	 //用于写入数据的套接字
int sockfd3;	 //用于保持数据的套接字
int addrlen;

struct sockaddr_in serveraddr1; //创建客户端结构体1
struct sockaddr_in serveraddr2; //创建客户端结构体2
struct sockaddr_in serveraddr3; //创建客户端结构体3
static struct shm_param para;	//创建共享内存结构体变量
struct modbus_node_list head;	//创建内核链表
struct list_head *pos;
struct modbus_node_list *tmp;
union val_t temp_val;

void *mysend(void *arg); //声明发送线程函数
void *myctrl(void *arg); //声明控制线程函数
int conver_endian_long(unsigned char *dst,
					   const unsigned char *src, int len); //大小端转换函数

int main(int argc, const char *argv[])
{
	addrlen = sizeof(struct sockaddr);
	sockfd1 = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd1 < 0)
	{
		perror("socket err");
		exit(-1);
	}
	bzero(&serveraddr1, addrlen);
	serveraddr1.sin_family = AF_INET;
	serveraddr1.sin_addr.s_addr = inet_addr("192.168.31.54");
	serveraddr1.sin_port = htons(500);
	printf("1\n");
	if (connect(sockfd1, (struct sockaddr *)&serveraddr1, addrlen) < 0)
	{
		perror("connect err");
		exit(-1);
	}
	
	addrlen = sizeof(struct sockaddr);
	sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd2 < 0)
	{
		perror("socket err");
		exit(-1);
	}
	bzero(&serveraddr2, addrlen);
	serveraddr2.sin_family = AF_INET;
	serveraddr2.sin_addr.s_addr = inet_addr("192.168.31.54");
	serveraddr2.sin_port = htons(501);
	printf("2\n");
	if (connect(sockfd2, (struct sockaddr *)&serveraddr2, addrlen) < 0)
	{
		perror("connect err");
		exit(-1);
	}
	
	addrlen = sizeof(struct sockaddr);
	sockfd3 = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd3 < 0)
	{
		perror("socket err");
		exit(-1);
	}
	bzero(&serveraddr3, addrlen);
	serveraddr3.sin_family = AF_INET;
	serveraddr3.sin_addr.s_addr = inet_addr("192.168.31.54");
	serveraddr3.sin_port = htons(502);
	printf("3\n");
	if (connect(sockfd3, (struct sockaddr *)&serveraddr3, addrlen) < 0)
	{
		perror("connect err");
		exit(-1);
	}
	
	pthread_t tid_send, tid_ctrl; //创建传送数据线程和控制线程
	if (pthread_create(&tid_send, NULL, mysend, NULL) != 0)
	{
		perror("mysend_create err.");
		return -1;
	}
	if (pthread_create(&tid_ctrl, NULL, myctrl, NULL) != 0)
	{
		perror("myctrl_create err.");
		return -1;
	}

	pthread_detach(tid_send); //将线程设为游离态
	pthread_detach(tid_ctrl);

	while (1)
	{
	}

	// close(sockfd1);
	// close(sockfd2);
	// close(sockfd3);
	return 0;
}

void *mysend(void *arg)
{	
	int ret = -1;
	ret = shm_init(&para, "modbus", sizeof(struct std_node) * MODBUS);
	if (ret < 0)
	{
		pthread_exit(NULL);
	}

	struct std_node *mb = shm_getaddr(&para);
	if (mb == NULL)
	{
		pthread_exit(NULL);
	}
	
	unsigned char send_buf_1[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x04,0x00,0x00,0x00,0x02};//温度
	unsigned char send_buf_2[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x04,0x00,0x02,0x00,0x02};//湿度

	unsigned char recv_buf[128] ;
	
	while (1)
	{
		sleep(1);
		for (int i = 0; i < 2; i++)
		{
			mb[i].old_val = mb[i].new_val;
		}

		//采集数据
		send(sockfd3, send_buf_1, 12, 0);
		ret = recv(sockfd3, recv_buf, 128, 0);
		if (ret < 0)
		{
			perror("recv err");
			continue;
		}
		for (int i = 0; i < ret; i++)
		{
			printf("%02x ", recv_buf[i]);
		}
		printf("\n");

		float *p = recv_buf + 9;
		float data = *p;
		mb[0].new_val.f_val = data;
		printf("%f\n",mb[0].new_val.f_val);
		
		send(sockfd3, send_buf_2, 12, 0);
		ret = recv(sockfd3, recv_buf, 128, 0);
		if (ret < 0)
		{
			perror("recv err");
			continue;
		}
		for (int i = 0; i < ret; i++)
		{
			printf("%02x ", recv_buf[i]);
		}
		printf("\n");
		float *pp = recv_buf + 9;
		mb[1].new_val.f_val = *pp;
		printf("%f\n",mb[1].new_val.f_val);

		for (int i = 0; i < 2; i++)
		{
			mb[i].key = 101 + i;		 //唯一键值
			mb[i].type = 3;				 //数据点类型
			mb[i].dev_type = 2;			 //属于边缘采集
			mb[i].ret = -1;
		}
		sleep(1);
	}
	close(sockfd3);
	pthread_exit(NULL);
}

void *myctrl(void *arg)
{
	int key;
	float val;

	cJSON *root = NULL;
	cJSON *item = NULL;
	cJSON *recv_root = NULL;

	struct msgbuf send_buf;				//创建消息队列发送变量
	struct msgbuf recv_buf;				//创建消息队列接收变量
	unsigned char modbus_ctry_buf[128]; //控制modbus发送指令变量

	unsigned char send_buf_3[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x05,0x00,0x00,0xff,0x00};//空调开
	unsigned char send_buf_4[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x05,0x00,0x00,0x00,0x00};//空调关
	unsigned char send_buf_5[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x06,0x00,0x00,0x00,0x00};//温度控制
	unsigned char send_buf_6[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x05,0x00,0x01,0xff,0x00};//灯开
	unsigned char send_buf_7[128] = {0x02,0xb7,0x00,0x00,0x00,0x06,0x01,0x05,0x00,0x01,0x00,0x00};//灯关


	send_buf.mtype = 1;
	recv_buf.mtype = 1;

	while (1)
	{
		if (msg_queue_recv("modbus_recv", &recv_buf, sizeof(recv_buf), 0, 0) > 0)
		{
			recv_root = cJSON_Parse(recv_buf.mdata);

			item = cJSON_GetObjectItem(recv_root, "data");
			item = cJSON_GetObjectItem(item, "key");
			key = atoi(cJSON_Print(item));

			item = cJSON_GetObjectItem(recv_root, "data");
			item = cJSON_GetObjectItem(item, "val");
			val = atof(item->valuestring);

			printf("%d %f\n", key, val);
		}
		else
		{
			perror("recv error:");
			break;
		}
		//modbus控制
		switch (key)
		{
		case 103:
			if(val == 1)
				send(sockfd2, send_buf_3, 12, 0);
			else
				send(sockfd2, send_buf_4, 12, 0);
			break;
		case 104:
				// float *pp = send_buf_5 + 9;
				printf("待开发\n");
				send(sockfd1, send_buf_5, 12, 0);
			break;
		case 105:
			if(val == 1)
				send(sockfd2, send_buf_6, 12, 0);
			else
				send(sockfd2, send_buf_7, 12, 0);
			break;
		}

		cJSON *root = cJSON_CreateObject();
		cJSON_AddItemToObject(root, "type", cJSON_CreateNumber(2));
		cJSON_AddItemToObject(root, "result", cJSON_CreateNumber(0));
		cJSON_AddItemToObject(root, "type", cJSON_CreateString("控制成功"));

		strcpy(send_buf.mdata, cJSON_Print(root));
		if (msg_queue_send("modbus_send", &send_buf, sizeof(send_buf), 0) < 0)
		{
			printf("msg_queue_send error\n");
			return -1;
		}
	}
	pause();

	pthread_exit(NULL);
}

int conver_endian_long(unsigned char *dst, const unsigned char *src, int len)
{
	int i = 0;

	if (len % 4 != 0)
	{
		printf("err len\n");
		return -1;
	}

	while (i < len)
	{
		dst[i] = src[i + 3];
		dst[i + 1] = src[i + 2];
		dst[i + 2] = src[i + 1];
		dst[i + 3] = src[i];
		i += 4;
	}

	return 0;
}